﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using UricaoWeb.Datos.ConexionBD.Propiedad;
using UricaoWeb.Datos.Excepciones.Propiedad;

namespace UricaoWeb.Datos.ConexionBD.Propiedad
{
    ///<summary>
    /// Clase Propiedad, representa una propiedad.
    /// Contiene los métodos para gestionar las mismas.
    ///</summary>
    public class ModeloPropiedad
    {
        #region Atributos

        private int _idPropiedad;
        private int _fkHotel;
        private string _nombrePropiedad;
        private string _tipoPropiedad;
        private string _descripcionPropiedad;
        private string _ubicacionPropiedad;
        private string _imagenPropiedad;
        private string _nombreHotel;

        #endregion 

        #region Propiedades

        public int IdPropiedad
        {
            get { return _idPropiedad; }
            set { _idPropiedad = value; }
        }

        public int FkHotel
        {
            get { return _fkHotel; }
            set { _fkHotel = value; }
        }

        public string NombrePropiedad
        {
            get { return _nombrePropiedad; }
            set { _nombrePropiedad = value; }
        }

        public string TipoPropiedad
        {
            get { return _tipoPropiedad; }
            set { _tipoPropiedad = value; }
        }

        public string DescripcionPropiedad
        {
            get { return _descripcionPropiedad; }
            set { _descripcionPropiedad = value; }
        }

        public string UbicacionPropiedad
        {
            get { return _ubicacionPropiedad; }
            set { _ubicacionPropiedad = value; }
        }

        public string ImagenPropiedad
        {
            get { return _imagenPropiedad; }
            set { _imagenPropiedad = value; }
        }

        public string NombreHotel
        {
            get { return _nombreHotel; }
            set { _nombreHotel = value; }
        }

        #endregion

        #region Metodos

        #region Seleccionar Procedimiento BD

        /// <summary>
        /// Función que recibe el tipo de consulta que se quiere realizar
        /// y devuelve el nombre del procedimiento almacenado en base de datos
        /// </summary>
        /// <param name="consulta">Tipo de la consulta a realizar</param>
        /// <returns>
        /// Nombre del procedimiento almacenado correspondiente a la consulta introducida
        /// </returns>
        private string SeleccionarProcedimiento(string consulta)
        {
            string procedimiento = "";
            switch (consulta)
            {
                case "nombre":
                    procedimiento = "dbo.consultarPropiedadesNombre";
                    return procedimiento;
                case "hotel":
                    procedimiento = "dbo.consultarPropiedadesHotel";
                    return procedimiento;
                case "id":
                    procedimiento = "dbo.consultarPropiedadesId";
                    return procedimiento;
                case "insertar":
                    procedimiento = "dbo.insertarPropiedad";
                    return procedimiento;
                case "hoteles":
                    procedimiento = "dbo.consultarPropiedadesHoteles";
                    return procedimiento;
                case "modificar":
                    procedimiento = "dbo.modificarPropiedad";
                    return procedimiento;
                case "eliminar":
                    procedimiento = "dbo.eliminarPropiedad";
                    return procedimiento;
            }
            return procedimiento;
        }

        #endregion

        #region Consultas

        /// <summary>
        /// Función para consultar propiedades de manera parametrizada, 
        /// ya sea por id, por nombre o por hotel al que pertenece
        /// </summary>
        /// <param name="parametro">Tipo de la consulta a realizar</param>
        /// <param name="valorBusqueda">Valor de la consulta a realizar</param>
        /// <returns>
        /// Devuelve una lista de propiedades
        /// </returns>
        public List<ModeloPropiedad> ConsultarPropiedadesConParametros(string parametro, string valorBusqueda)
        {
            List<ModeloPropiedad> propiedades = new List<ModeloPropiedad>();
            string comandoProcedimiento = SeleccionarProcedimiento(parametro); 
            OperacionesBD conexionBD = new OperacionesBD();
            
            try
            {
                SqlCommand comandoSeleccion = new SqlCommand(comandoProcedimiento, conexionBD._cn);
                comandoSeleccion.CommandType = CommandType.StoredProcedure;
                conexionBD._cn.Open();
                comandoSeleccion.Parameters.AddWithValue("@parametro", valorBusqueda);
                SqlDataReader readerBD = comandoSeleccion.ExecuteReader();

                while (readerBD.Read())
                {
                    ModeloPropiedad propiedad = new ModeloPropiedad();

                    propiedad.IdPropiedad = readerBD.GetInt32(0);
                    propiedad.FkHotel = readerBD.GetInt32(1);
                    propiedad.NombrePropiedad = readerBD.GetString(2);
                    propiedad.TipoPropiedad = readerBD.GetString(3);
                    propiedad.DescripcionPropiedad = readerBD.GetString(4);
                    propiedad.UbicacionPropiedad = readerBD.GetString(5);
                    propiedad.ImagenPropiedad = readerBD.GetString(6);
                    propiedad.NombreHotel = readerBD.GetString(8);

                    propiedades.Add(propiedad);
                }
            }
            catch (SqlException e)
            { throw new PropiedadException("PRO-001 Error relacionado con la base de datos SQL Server (ConsultarPropiedadesConParametros)", e); }
            catch (Exception e)
            { throw new PropiedadException("PRO-002 Error al consultar propiedades (ConsultarPropiedadesConParametros)", e); }
            finally 
            { conexionBD._cn.Close(); }

            return propiedades;
        }

        /// <summary>
        /// Función para consultar los hoteles a los que pertenecen las propiedades
        /// </summary>
        /// <param name="parametro">Tipo de la consulta a realizar</param>
        /// <returns>
        /// Devuelve una lista con los distintos hoteles dueños de las propiedades
        /// </returns>
        public List<Hotel> ConsultarPropiedadesHoteles(string parametro)
        {
            List<Hotel> propiedades = new List<Hotel>();
            string comandoProcedimiento = SeleccionarProcedimiento(parametro);
            OperacionesBD conexionBD = new OperacionesBD();
            SqlCommand comandoSeleccion = new SqlCommand(comandoProcedimiento, conexionBD._cn);
            comandoSeleccion.CommandType = CommandType.StoredProcedure;
            SqlDataReader readerBD;

            try
            {
                conexionBD._cn.Open();
                readerBD = comandoSeleccion.ExecuteReader();

                while (readerBD.Read())
                {
                    Hotel hotel = new Hotel();
                    hotel.IdHotel = readerBD.GetInt32(0);
                    hotel.nombreHotel = readerBD.GetString(1);
                    propiedades.Add(hotel);
                }
            }
            catch (SqlException e)
            { throw new PropiedadException("PRO-003 Error relacionado con la base de datos SQL Server (ConsultarPropiedadesHoteles)", e); }
            catch (Exception e)
            { throw new PropiedadException("PRO-004 Error al consultar propiedades (ConsultarPropiedadesHoteles)", e); }
            finally
            { conexionBD._cn.Close(); }

            return propiedades;
        }

        /// <summary>
        /// Función para consultar los tipos de propiedades
        /// </summary>
        /// <returns>
        /// Devuelve una lista con los distintos tipos de propiedad
        /// </returns>
        public List<String> ConsultarTipoPropiedad()
        {
            List<String> listaTipos = new List<String>();
            listaTipos.Add("Terreno");
            listaTipos.Add("Local");
            listaTipos.Add("Edificio");
            return listaTipos;
        }

        #endregion

        #region Agregar Propiedad

        /// <summary>
        /// Función para agregar una propiedad
        /// </summary>
        /// <param name="propiedad">Objeto del tipo propiedad, es la propiedad a agregar</param>
        /// <returns>
        /// Devuelve true si se agrego la propiedad correctamente y false si no
        /// </returns>
        public bool AgregarPropiedad(ModeloPropiedad propiedad)
        {
            string comandoProcedimiento = SeleccionarProcedimiento("insertar");
            OperacionesBD conexionBD = new OperacionesBD();
            SqlCommand comandoInsert = new SqlCommand(comandoProcedimiento, conexionBD._cn);
            comandoInsert.CommandType = CommandType.StoredProcedure;

            try
            {
                conexionBD._cn.Open();
                comandoInsert.Parameters.AddWithValue("@fkHotel", propiedad.FkHotel);
                comandoInsert.Parameters.AddWithValue("@nombrePropiedad", propiedad.NombrePropiedad);
                comandoInsert.Parameters.AddWithValue("@tipoPropiedad", propiedad.TipoPropiedad);
                comandoInsert.Parameters.AddWithValue("@descripcionPropiedad", propiedad.DescripcionPropiedad);
                comandoInsert.Parameters.AddWithValue("@ubicacionPropiedad", propiedad.UbicacionPropiedad);
                comandoInsert.Parameters.AddWithValue("@imagenPropiedad", propiedad.ImagenPropiedad);
                comandoInsert.Parameters.AddWithValue("@statusPropiedad", "Activo");

                int flagInsert = comandoInsert.ExecuteNonQuery();
                if (flagInsert > 0) return true;
            }
            catch (SqlException e)
            { throw new PropiedadException("PRO-005 Error relacionado con la base de datos SQL Server (AgregarPropiedad)", e); }
            catch (Exception e)
            { throw new PropiedadException("PRO-006 Error al agregar propiedades (AgregarPropiedad)", e); }
            finally
            { conexionBD._cn.Close(); }

            return false;
        }

        #endregion

        #region Modificar Propiedad

        /// <summary>
        /// Función para modificar una propiedad
        /// </summary>
        /// <param name="propiedad">Objeto del tipo propiedad, es la propiedad a modificar</param>
        /// <returns>
        /// Devuelve true si se modificó la propiedad correctamente y false si no
        /// </returns>
        public bool ModificarPropiedad(ModeloPropiedad propiedad)
        {
            string comandoProcedimiento = SeleccionarProcedimiento("modificar");
            OperacionesBD conexionBD = new OperacionesBD();
            SqlCommand comandoUpdate = new SqlCommand(comandoProcedimiento, conexionBD._cn);
            comandoUpdate.CommandType = CommandType.StoredProcedure;

            try
            {
                conexionBD._cn.Open();
                comandoUpdate.Parameters.AddWithValue("@idPropiedad", propiedad.IdPropiedad);
                comandoUpdate.Parameters.AddWithValue("@fkHotel", propiedad._fkHotel);
                comandoUpdate.Parameters.AddWithValue("@nombrePropiedad", propiedad.NombrePropiedad);
                comandoUpdate.Parameters.AddWithValue("@tipoPropiedad", propiedad.TipoPropiedad);
                comandoUpdate.Parameters.AddWithValue("@descripcionPropiedad", propiedad.DescripcionPropiedad);
                comandoUpdate.Parameters.AddWithValue("@ubicacionPropiedad", propiedad.UbicacionPropiedad);
                comandoUpdate.Parameters.AddWithValue("@imagenPropiedad", propiedad.ImagenPropiedad);

                int flagUpdate = comandoUpdate.ExecuteNonQuery();
                if (flagUpdate > 0) return true;
            }
            catch (SqlException e)
            { throw new PropiedadException("PRO-007 Error relacionado con la base de datos SQL Server (ModificarPropiedad)", e); }
            catch (Exception e)
            { throw new PropiedadException("PRO-008 Error al modificar propiedades (ModificarPropiedad)", e); }
            finally
            { conexionBD._cn.Close(); }
            
            return false;
        }

        #endregion

        #region Eliminar Propiedad

        /// <summary>
        /// Función para eliminar una propiedad
        /// </summary>
        /// <param name="propiedad">Objeto del tipo propiedad, es la propiedad a eliminar</param>
        /// <returns>
        /// Devuelve true si se modificó la propiedad correctamente y false si no
        /// </returns>
        public bool EliminarPropiedad(int idPropiedad)
        {
            string comandoProcedimiento = SeleccionarProcedimiento("eliminar"); 
            OperacionesBD conexionBD = new OperacionesBD();
            SqlCommand comandoUpdate = new SqlCommand(comandoProcedimiento, conexionBD._cn);
            comandoUpdate.CommandType = CommandType.StoredProcedure;

            try
            {
                conexionBD._cn.Open();
                comandoUpdate.Parameters.AddWithValue("@idPropiedad", idPropiedad);

                int flagDelete = comandoUpdate.ExecuteNonQuery();
                if (flagDelete > 0) return true;
            }
            catch (SqlException e)
            { throw new PropiedadException("PRO-009 Error relacionado con la base de datos SQL Server (EliminarPropiedad)", e); }
            catch (Exception e)
            { throw new PropiedadException("PRO-010 Error al eliminar propiedades (EliminarPropiedad)", e); }
            finally
            { conexionBD._cn.Close(); }

            return false;
        }

        #endregion

        #endregion
    }
}